#include "Ship.h"

BasicShip::BasicShip() : BaseIndexedGraphicalEntity()
{
	EnterWarp = false;
	IsWarping = false;
	ExitWarp = false;
	CanToggleWarp = true;
	LastWarp = 0;
}

BasicShip::BasicShip(IDirect3DDevice9 *nDevice) : BaseIndexedGraphicalEntity(nDevice), BoundingBox(nDevice)
{
	Angles = D3DXVECTOR3(0,0,0);
	EnterWarp = false;
	IsWarping = false;
	ExitWarp = false;
	CanToggleWarp = true;
	LastWarp = 0;
}

BasicShip::~BasicShip()
{

}

void BasicShip::SetPosition( D3DXVECTOR3 nPosition )
{
	Position = nPosition;
}

void BasicShip::SetVelocity( D3DXVECTOR3 nVelocity )
{
	Velocity = nVelocity;
}

void BasicShip::Update( float dt )
{
	LastWarp += dt;

	if(LastWarp >= 1.f)
	{
		CanToggleWarp = true;
	}

	BoundingBox.SetAngles(Angles);
	BoundingBox.SetPosition(this->Position);
	BoundingBox.Update(dt);
	BaseIndexedGraphicalEntity::Update(dt);
}

void BasicShip::Render( void )
{
	BaseIndexedGraphicalEntity::Render();
}

D3DXVECTOR3 BasicShip::GetAngles( void )
{
	return Angles;
}

void BasicShip::SetAngles(D3DXVECTOR3 nAngles)
{
	Angles = nAngles;
}

void BasicShip::SetAngles(float nX, float nY, float nZ)
{
	Angles.x = nX;
	Angles.y = nY;
	Angles.z = nZ;
}

void BasicShip::ToggleWarp( void )
{
	if(CanToggleWarp)
	{
		if(!IsWarping)
		{
			EnterWarp = true;
			IsWarping = true;
			ExitWarp = false;
		}
		else
		{
			EnterWarp = false;
			IsWarping = true;
			ExitWarp = true;
		}
		CanToggleWarp = false;
		LastWarp = 0;
	}
}

bool BasicShip::GetIsWarping( void )
{
	return IsWarping;
}
bool BasicShip::GetEnterWarping( void )
{
	return EnterWarp;
}

bool BasicShip::GetExitWarping( void )
{
	return ExitWarp;
}

TestShip::TestShip() : BasicShip()
{

}

TestShip::TestShip( IDirect3DDevice9 *nDevice, float nMass, D3DXVECTOR3 ShipSize) : BasicShip(nDevice)
{
	CreateCube(ShipSize);
	BoundingBox.InitCollisionBox(ShipSize);
	Thrusters.reserve(4);
	Mass = nMass;

	D3DXMatrixIdentity(&RotationMatrix);
	D3DXMatrixIdentity(&TransMat);

	isDying = false;
	//isDead = false;

	DeathExplosion = new Explosion(nDevice, "Explosion.fx", "Main", Position, 2000, .0001f);
	DeathTime = 0;
}

TestShip::~TestShip( void )
{
	for(unsigned int i = 0; i < Thrusters.size(); ++i)
	{
		delete Thrusters[i];
	}

	if(DeathExplosion != NULL)
	{
		delete DeathExplosion;
		DeathExplosion = NULL;
	}
}

void TestShip::InitThrusters( float nThrust )
{
	BasicThruster *temp; 
	D3DXVECTOR3 tempVec = BoundingBox.GetHalfVector();
	temp = new BasicThruster(Device, D3DXVECTOR3(tempVec.x,tempVec.y,-tempVec.z), D3DXVECTOR3(0,0,0), nThrust);
	temp->CreateCube(D3DXVECTOR3(.2f,.2f,.2f));
	temp->SetOffset(D3DXVECTOR3(tempVec.x,tempVec.y,-tempVec.z));
	Thrusters.push_back(temp);

	temp = new BasicThruster(Device, D3DXVECTOR3(tempVec.x,-tempVec.y,-tempVec.z), D3DXVECTOR3(0,0,0), nThrust);
	temp->CreateCube(D3DXVECTOR3(.2f,.2f,.2f));
	temp->SetOffset(D3DXVECTOR3(tempVec.x,-tempVec.y,-tempVec.z));
	Thrusters.push_back(temp);

	temp = new BasicThruster(Device, D3DXVECTOR3(-tempVec.x,tempVec.y,-tempVec.z), D3DXVECTOR3(0,0,0), nThrust);
	temp->CreateCube(D3DXVECTOR3(.2f,.2f,.2f));
	temp->SetOffset(D3DXVECTOR3(-tempVec.x,tempVec.y,-tempVec.z));
	Thrusters.push_back(temp);

	temp = new BasicThruster(Device, D3DXVECTOR3(-tempVec.x,-tempVec.y,-tempVec.z), D3DXVECTOR3(0,0,0), nThrust);
	temp->CreateCube(D3DXVECTOR3(.2f,.2f,.2f));
	temp->SetOffset(D3DXVECTOR3(-tempVec.x,-tempVec.y,-tempVec.z));
	Thrusters.push_back(temp);

	ThrusterThrottle.push_back(0);
	ThrusterThrottle.push_back(0);
	ThrusterThrottle.push_back(0);
	ThrusterThrottle.push_back(0);

	Thrust = nThrust;

}

void TestShip::Update( float dt )
{
	D3DXMatrixRotationYawPitchRoll(&RotationMatrix, Angles.x, Angles.y, Angles.z);
	if(!IsWarping)
	{
		for(unsigned int j = 0; j < ThrusterThrottle.size(); ++j)
		{
			D3DXVECTOR3 ThrustVec = D3DXVECTOR3(0,0,1) * ((((float(ThrusterThrottle[j])/100)*(Thrust*Thrusters.size()))/Mass)*dt);
			D3DXVec3TransformCoord(&ThrustVec, &ThrustVec, &RotationMatrix);
			Velocity += ThrustVec * 5; 
		}
	}
	else
	{
		for(UINT j = 0; j < ThrusterThrottle.size(); ++j)
		{
			ThrusterThrottle[j] = 0;
		}
		if(EnterWarp)
		{
			D3DXVECTOR3 TempVelocity(0,0,1);
			D3DXVec3TransformCoord(&TempVelocity, &TempVelocity, &RotationMatrix);
			Velocity += TempVelocity * 20;

			if(D3DXVec3LengthSq(&Velocity) >= (WARP_SPEED*WARP_SPEED))
			{
				D3DXVec3Normalize(&Velocity, &Velocity);
				Velocity *= WARP_SPEED;
				EnterWarp = false;
			}
		}
		else if(ExitWarp)
		{
			D3DXVECTOR3 TempVelocity(0,0,10);
			D3DXMatrixRotationYawPitchRoll(&RotationMatrix, Angles.x, Angles.y, Angles.z);
			D3DXVec3TransformCoord(&TempVelocity, &TempVelocity, &RotationMatrix);
			Velocity -= Velocity * dt;

			if(D3DXVec3LengthSq(&Velocity) < 300)
			{
				ExitWarp = false;
				IsWarping = false;
			}
		}
		else
		{
			D3DXVECTOR3 TempVelocity(0,0,1);
			D3DXVec3TransformCoord(&TempVelocity, &TempVelocity, &RotationMatrix);
			Velocity += TempVelocity * 20;

			if(D3DXVec3LengthSq(&Velocity) >= (WARP_SPEED*WARP_SPEED))
			{
				D3DXVec3Normalize(&Velocity, &Velocity);
				Velocity *= WARP_SPEED;
				EnterWarp = false;
			}
		}
	}

	if(isDying && DeathExplosion->GetIsActive())
	{
		Velocity *= 0;
		DeathExplosion->SetPosition(Position);
		DeathTime += dt;
		DeathExplosion->SetTime(DeathTime);
		ThrusterThrottle[0] = 0;
		ThrusterThrottle[1] = 0;
		ThrusterThrottle[2] = 0;
		ThrusterThrottle[3] = 0;

		if(DeathTime >= 7.f)
		{
			isDying = false;
			DeathExplosion->Deactivate();
			Reset();
		}
	}

	

	DeathExplosion->Update(dt);

	BasicShip::Update(dt);

	for(unsigned int i = 0; i < Thrusters.size(); ++i)
	{
		if(ThrusterThrottle[i] > 0 || ThrusterThrottle[i] < 0)
		{
			Thrusters[i]->Activate();
			Thrusters[i]->SetSpawnVelocity(Velocity);
			//Thrusters[i]->SetSpawnVelocity(D3DXVECTOR3(0,0,0));
		}
		else
			Thrusters[i]->Deactivate();

		Thrusters[i]->SetVelocity(D3DXVECTOR3(0,0,0));
		Thrusters[i]->Update(dt);
		Thrusters[i]->SetAngles(Angles);
		//D3DXVECTOR3 tempVec = BoundingBox.GetHalfVector();
		D3DXVECTOR3 RotatedVec = Thrusters[i]->GetOffset();

		D3DXVec3TransformCoord(&RotatedVec, &RotatedVec, &RotationMatrix);
		Thrusters[i]->SetPosition(Position + RotatedVec);

	}
}

void TestShip::Render( void )
{
	HRESULT r = S_OK;
	//BoundingBox.Render();

	D3DXMatrixTranslation(&TransMat, Position.x, Position.y, Position.z);
	r = Effect->SetMatrix("gWVPMat", &(RotationMatrix * TransMat * WVPMat));
	Effect->CommitChanges();

	if(DeathExplosion->GetIsActive())
	{
		DeathExplosion->Render();
	}
	else
	{
		for(unsigned int i = 0; i < Thrusters.size(); ++i)
		{
			D3DXMatrixTranslation(&TransMat, Thrusters[i]->GetPosition().x, Thrusters[i]->GetPosition().y, Thrusters[i]->GetPosition().z);
			r = Effect->SetMatrix("gWVPMat", &( RotationMatrix * TransMat * WVPMat));
			Thrusters[i]->SetWVPMatrix(/*TransMat */ WVPMat);
			Effect->CommitChanges();
			Thrusters[i]->Render();
		}
		D3DXMatrixTranslation(&TransMat, Position.x, Position.y, Position.z);
		r = Effect->SetMatrix("gWVPMat", &(RotationMatrix * TransMat * WVPMat));
		Effect->CommitChanges();
		BoundingBox.Render();
		BasicShip::Render();
	}
}

void TestShip::SetEffect(ID3DXEffect *nEffect)
{
	Effect = nEffect;
}

void TestShip::SetWVPMat(D3DXMATRIX nWVP)
{
	WVPMat = nWVP;

	for(unsigned int i = 0; i < Thrusters.size(); ++i)
	{
		Thrusters[i]->SetWVPMatrix(nWVP);
	}
	DeathExplosion->SetWVPMatrix(nWVP);
}

void TestShip::SetEyePosition(const D3DXVECTOR3 &nVector)
{
	for(unsigned int i = 0; i < Thrusters.size(); ++i)
	{
		Thrusters[i]->SetEyePosition(nVector);
	}
	DeathExplosion->SetCameraPosition(nVector);
}

void TestShip::SetForwardThrottle(short nThrottle)
{
	if(nThrottle < 0)
		nThrottle = -nThrottle;

	if(nThrottle > 100)
		nThrottle = 100;
		
	for(unsigned int i = 0; i < ThrusterThrottle.size(); ++i)
	{
		ThrusterThrottle[i] = nThrottle;
		Thrusters[i]->SetThrottle(nThrottle);
	}
}

void TestShip::SetBackwardThrottle(short nThrottle)
{
	if(nThrottle < 0)
		nThrottle = -nThrottle;

	if(nThrottle > 100)
		nThrottle = 100;

	for(unsigned int i = 0; i < ThrusterThrottle.size(); ++i)
	{
		ThrusterThrottle[i] = -nThrottle;
		Thrusters[i]->SetThrottle(-nThrottle);
	}
}

void TestShip::SetLeftThrottle(short nThrottle)
{

}

void TestShip::SetRightThrottle(short nThrottle)
{

}

short TestShip::GetThrottle( void )
{
	return ThrusterThrottle[0];
}

void TestShip::Reset( void )
{
	isDying = false;
	DeathExplosion->Deactivate();
	DeathExplosion->Reset();
	DeathTime = 0;

	EnterWarp = false;
	IsWarping = false;
	ExitWarp = false;

	CanToggleWarp = true;
	LastWarp = 0.f;

	bool Colliding = true;
	int RandomNum = 0;

	while(Colliding)
	{
		Colliding = false;
		int RandomNum = rand() % 5000;
		Position.x = float(RandomNum);

		RandomNum = rand() % 5000;
		Position.y = float(RandomNum);

		RandomNum = rand() % 5000;
		Position.z = float(RandomNum);

		for(UINT i = 0; i < Globals->Planets.size(); ++i)
		{
			if(CollisionTest::IsColliding(Globals->Planets[i]->MainSphere, BoundingBox.BoundingBox))
			{
				Colliding = true;
			}
		}

	}

}

void TestShip::KillMe( void )
{
	EnterWarp = false;
	IsWarping = false;
	ExitWarp = false;
	isDying = true;
	DeathExplosion->SetTime(0);
	DeathExplosion->Activate();
}

bool TestShip::GetIsDying( void )
{
	return isDying;
}